#include <iostream>
#include <string.h>
using std::cout;
using std::endl;
using std::ostream;

class String{
public:
    // 构造函数
    String();
    String(const char* pstr);
    ~String();

    // 赋值函数
    String(const String& rhs);
    String(String&& rhs);
    String& operator= (const String& rhs);
    String& operator= (String&& rhs);

    // 输出流重载
    const char* c_str() const;
    friend ostream& operator<< (ostream& os, const String& rhs);

private:
    char* _pstr;
};

String::String()
    : _pstr(new char[1]()){
}

String::String(const char* pstr)
    :_pstr(new char[strlen(pstr) + 1]()){
    strcpy(_pstr, pstr);
}

String::~String(){
    delete []_pstr;
}

String::String(const String& rhs)
    :_pstr(new char[strlen(rhs._pstr) + 1]()){
    strcpy(_pstr, rhs._pstr);    
}

String::String(String&& rhs)
    :_pstr(rhs._pstr){
    rhs._pstr = nullptr;
}

String& String::operator= (const String& rhs){
    if(this != &rhs){
       delete []_pstr;

       _pstr = new char[strlen(rhs._pstr) + 1]();
       strcpy(_pstr, rhs._pstr);
    }
    return *this;
}

String& String::operator= (String&& rhs){
    if(this != &rhs){
        delete [] _pstr;

        _pstr = rhs._pstr;
        rhs._pstr = nullptr;
    }
    return *this;
}

const char* String::c_str() const{
    return _pstr;
}

ostream &operator<< (ostream& os, const String& rhs){
    if(rhs._pstr){
        os << rhs._pstr;
    }
    return os;
}

void test(){
    // 1. 基础构造函数测试
    String s1;                     // 默认构造
    String s2("Hello");            // C字符串构造
    String s3 = s2;                // 拷贝构造
    String s4 = std::move(s2);     // 移动构造

    // 2. 赋值运算符测试
    String s5;
    s5 = s3;                       // 拷贝赋值
    String s6;
    s6 = std::move(s3);            // 移动赋值

    // 3. 自赋值测试
    s4 = s4;                       // 拷贝自赋值
    s6 = std::move(s6);            // 移动自赋值

    // 4. 链式赋值测试
    String s7, s8, s9;
    s7 = s8 = s9 = "Chain";        // 链式赋值

    // 5. 空字符串测试
    String s10("");
    String s11 = s10;
    s11 = std::move(s10);

    // 6. 输出测试（需先修正operator<<）
    std::cout << "s2 after move: " << (s2.c_str() ? s2.c_str() : "nullptr") << std::endl;
    std::cout << "s4: " << s4.c_str() << std::endl;
    std::cout << "s7: " << s7.c_str() << std::endl;
}

int main()
{
    test();
    return 0;
}

